/* Hilo de espera por TRAPS */

package clientegestionred;

import common.Cons;
import common.Consulta;
import common.SesionSNMP;

import java.io.IOException;
import java.util.Vector;

import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.CommunityTarget;
import org.snmp4j.MessageDispatcher;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.mp.*;
import org.snmp4j.smi.*;
import org.snmp4j.transport.*;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;


public class GestorDeTraps extends Thread implements CommandResponder, Cons{
     
    private SesionSNMP readSesion; //sesion de lectura

    private Vector variableBinding; //almacenar las variableBindings

    private Consulta consulta; //para hacer consultas

    /* Constructores */
    public GestorDeTraps(){}

    public GestorDeTraps(SesionSNMP readSesion){
        this.readSesion = readSesion;
    }


    /* Iniciar el hilo */
    public void run(){

        try
        {
            listen(new UdpAddress(IP_GESTOR + "/" + TRAP_PORT));
        }
        catch (IOException e)
        {
            System.err.println("Error en la escucha de traps");
            System.err.println("Exception Message = " + e.getMessage());
        }
    } //run

    /* Ponerse a la escucha de traps */
    private synchronized void listen(TransportIpAddress address) throws IOException
    {
        AbstractTransportMapping transport;
        if (address instanceof TcpAddress){
            transport = new DefaultTcpTransportMapping((TcpAddress) address);
        }
        else{
            transport = new DefaultUdpTransportMapping((UdpAddress) address);
        }

        ThreadPool threadPool = ThreadPool.create("DispatcherPool", 10);
        MessageDispatcher mtDispatcher = new MultiThreadedMessageDispatcher(threadPool,
                new MessageDispatcherImpl());

        // Añadir modelos de procesamiento de mensajes
        mtDispatcher.addMessageProcessingModel(new MPv1());
        mtDispatcher.addMessageProcessingModel(new MPv2c());

        // Crear Target
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString(TRAP_COMMUNITY));

        Snmp snmp = new Snmp(mtDispatcher, transport);
        snmp.addCommandResponder(this);

        transport.listen();

        // Esperar por mensajes entrantes
        synchronized (this) {
            try {
                this.wait(); 
            } catch (InterruptedException ex){
                Thread.currentThread().interrupt();
            }
        }

        // Parar el hilo y cerrarlo todo
        threadPool.stop();
        snmp.close();

    } //listen

    /* Metodo que sera llamado cuando se reciba una PDU en el puerto
    especificado en el metodo listen()*/
    public synchronized void processPdu(CommandResponderEvent cmdRespEvent)
    {
        PDU pdu = cmdRespEvent.getPDU();
        if (pdu != null)
        {
            int pduType = pdu.getType();
            if ((pduType == PDU.TRAP) || (pduType == PDU.V1TRAP))
            {
                //PDU recibida de tipo TRAP
                VariableBinding v = (VariableBinding)pdu.getVariableBindings().get(0);
                String valor = v.getVariable().toString();
                if (valor.equalsIgnoreCase("SOBRECARGA"))
                {
                    //El TRAP recibido indica una sobrecarga en el equipo.
                    muestraSobracarga();
                    
                } else{
                    variableBinding = pdu.getVariableBindings();
                    Variable ifEntry = ((VariableBinding)(variableBinding.get(2))).
                            getVariable();
                    int interfaceNumber = ifEntry.toInt();
                    consulta = new Consulta(readSesion);
                    OID [] ifDescr = new OID []{new OID("1.3.6.1.2.1.2.2.1.2."+
                            interfaceNumber)};
                    Variable [] response = new Variable []{};
                    try {
                        response = consulta.get(ifDescr);
                    } catch (IOException ex) {}

                    Variable ifOperStatus = ((VariableBinding)(variableBinding.get(4))).
                            getVariable();
                    int Oper = ifOperStatus.toInt();
                    //Notificar caida del interfaz.
                    System.out.println("\n\n     ********************* "
                            + "NOTIFICACIÓN IMPORTANTE *********************");
                    if(Oper == 2) System.out.println("\tEl interfaz " +
                            response[0].toString()+" se ha caido.");
                    //Notificar levantamiento del interfaz.
                    else System.out.println("\t\tEl interfaz "+response[0].
                            toString() + " se ha levantado.");
                    System.out.println("     *********************************"
                            + "**********************************\n\n");
                    System.out.flush();
                } //else
            } //if pdutype
        } //if !null
        
    } //processPdu

    /* Metodo para despertar y salir del wait() */
    public void despierta(){
        synchronized (this) {
            try {
                this.notify();
            } catch (Exception ex){
                Thread.currentThread().interrupt();}
        }
    }

    /* Imprimir el mensaje de sobrecarga */
    private void muestraSobracarga() {
        System.out.println("\n\n     ********************* "
                            + "NOTIFICACIÓN IMPORTANTE *********************");
        System.out.println("     *                                "
                            + "                                 *");
        System.out.println("     * El equipo esta sobrecargado y "
                            + "puede llegar a colapsarse.        *");
        System.out.println("     * Por favor, intente solucionar los "
                            + "problemas.                    *");
        System.out.println("     *                                "
                            + "                                 *");
        System.out.println("     *********************************"
                            + "**********************************\n\n");
        System.out.flush();
    } //muestraSobrecarga

} //class
